

const requestAnimFrame = (function () {
    return (
        window.requestAnimationFrame ||
        // @ts-ignore
        window.webkitRequestAnimationFrame ||
        // @ts-ignore
        window.mozRequestAnimationFrame ||
        function (callback) {
            return window.setTimeout(callback, 1000 / 60);
        }
    );
})();



export class ScrollPosition {
    // 记录住运动函数，用于取消函数
    private animationId: any;

    /**
     * @description: 获取
     * @return {*}
     * @author: tao wenbo 2419421809@qq.com
     */
    public static position() {
        // @ts-ignore
        return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop;
    }

    /**
     * @description: 滚动到指定位置
     * @param {number} position 绝对位置
     * @return {*}
     * @author: tao wenbo 2419421809@qq.com
     */
    public static move(position: number) {
        document.documentElement.scrollTop = position;
        // @ts-ignore
        document.body.parentNode.scrollTop = position;
        document.body.scrollTop = position;
    }
    
    /**
     * @description: 取消动画
     * @param {any} animationId
     * @return {*}
     * @author: tao wenbo 2419421809@qq.com
     */    
    public cancelAnimation( animationId: any ) {
        try {
            cancelAnimationFrame(animationId);
        } catch (error) {}
        try {
            // @ts-ignore
            webkitCancelAnimationFrame(animationId);
        } catch (error) {}
        try {
            // @ts-ignore
            mozCancelAnimationFrame(animationId);
        } catch (error) {}
        try {
            clearTimeout(animationId);
        } catch (error) {}
    }

    /**
     * @description: 平滑滚动
     * @param {number} targetPosition 绝对位置
     * @param {number} duration 延时
     * @param {Function} callback 回调
     * @return {*}
     * @author: tao wenbo 2419421809@qq.com
     */
    smoothScrollTo(targetPosition: number, duration: number, callback?: Function): void {
        const _this = this;
        if (duration === 0) {
            ScrollPosition.move(targetPosition);
            return;
        }
        let isScrolling = false;
        let animationStartTime: number | null = null;

        // 当手指触碰滚轮移动的时候取消滚动
        window.addEventListener("touchstart", stopScrollAnimation, { passive: false });
        window.addEventListener("touchmove", stopScrollAnimation, { passive: false });
        window.addEventListener("wheel", stopScrollAnimation, { passive: false });

        // 动画滚动到指定位置
        function animateScrollTo(): void {
            const startPosition = ScrollPosition.position();
            const distance = targetPosition - startPosition;

            function step(timestamp: number): void {
                if (!animationStartTime) {
                    animationStartTime = timestamp;
                }

                const progress = (timestamp - animationStartTime) / duration;
                const easedProgress = progress * (2 - progress);
                const newPosition = startPosition + distance * easedProgress;

                ScrollPosition.move(newPosition);

                if (progress < 1 && isScrolling) {
                    // 未达到目标位置，继续执行下一帧动画
                    _this.animationId = requestAnimFrame(step);
                }
                if (progress >= 1) {
                    isScrolling = false;
                    stopScrollAnimation()
                    if(callback) callback()
                }
            }

            isScrolling = true;
            _this.animationId = requestAnimFrame(step);
        }

        // 停止滚动动画
        function stopScrollAnimation(): void {
            _this.cancelAnimation(_this.animationId);
            isScrolling = false;
            if(callback) callback()
        }

        animateScrollTo();
    }
}
